KayeILSQL-04-Oracle Integrity Constraints

Contents

Based On

References

Database Design Process

Definition of Integrity Constraints

Types of Integrity Constraints

A Section of the ER Model of the European Parliament

Table Instance Chart

SQL — CREATE TABLE Statement

INLINE and OUT-OF-LINE Constraint Specifications

SQL — NOT NULL CONSTRAINT

SQL — UNIQUE CONSTRAINT

SQL — PRIMARY KEY CONSTRAINT

SQL — FOREIGN KEY CONSTRAINT

SQL — CHECK CONSTRAINT

For More on Integrity Constraints

References

Based On

This text on SQL is based on the Oracle Database using the EP-European Parliament as Data Model.

The European Parliament (EP) is the parliamentary institution of the European Union (EU).

The European Parliament is elected by the citizens of the European Union to represent their interests.

Its origins go back to the 1950s and the founding Treaties. Since 1979 its members have been directly elected by the citizens of the EU.

Elections are held every five years, and every EU citizen is entitled to vote, and to stand as a candidate, wherever they live in the EU. Parliament thus expresses the democratic will of the European Union's nearly 500 million citizens and it represents their interests in discussions with the other EU institutions.

The European Parliament model and data used in this SQL text, are based on the elections which were held in June 2004. The European Parliament of 2004 elections had 785 members from all 27 EU countries.

The sources for the data, which are all freely obtainable from the European Union website, and from several leaflets of the EU institutions, are listed in the References section.

These sources are used to create the fictitious Business Narrative of the "Data Modelling and Normalization" Chapter.

We called this Business Narrative; "the Story of the European Union" which explains about the EU and EP, for purposes of Data Modeling.

The Story of the European Union is the last Chapter of Kaye is Learning SQL.

Beautiful Lagerstroemia / Crape Myrtle Tree
Beautiful Crape Myrtle Tree

References

The knowledge in the following sections are based on my personal work experience, as well as on several Oracle Documentation, which are freely downloadable from Oracle websites.

You can find a list of these documents in the References.

The name of the documents may change in time.

You can refer to the Oracle Documentation if you need more detailed information on any of the topics in this text.

Breath of Fresh Air

Database Design Process

A Database Design is derived from an Entity Relationship(ER) Model.

During the Database Design Process, using the ER Model, we map:

Database Objects are derived from ER Models.

In Chapter 2—Data Modeling and Normalization, we learned about "ER Modeling".

We listened to the Story of the European Union from a Business Analyst working in the "IT Organization of the European Union".

The Story of the European Union told us by the Business Analyst is also called, the Business Narrative of the Organization.

We concentrated on the European Parliament institute of the European Union.

Using this Business Narrative of the Organization, we derived;

All this information, some of which was fictitious, enabled us to create a Data Model of the European Parliament.

At the end of the Modeling and Normalization processes, we came up with an ER(Entity Relationship) Model in Third Normal Form(3NF), which you can find down below.

Our ER Model of the European Parliament in Third Normal Form(3NF)
Our ER Model of the European Parliament

According to the "Application Design Cycle" which we have seen in Chapter 2—Data Modeling and Normalization, the Database Design process comes next:

Application Design Cycle

In this chapter, we will focus on the structures/objects called Integrity Constraints, and How to Create Constraints which is part of the Oracle Database Design Process.

Definition of Integrity Constraint

An Integrity Constraint is a named rule that restricts the values for one or more columns in a table.

The CONSTRAINT clause is used to define an Integrity Constraint.

Oracle server uses constraints to ensure Data Integrity, i.e. to prevent invalid data entry into the database tables.

Constraints enforce Business Rules at the table level.

Constraints prevent deletion of a table if there are dependencies from other tables.

Types of Integrity Constraints

NOT NULL Constraint

NOT NULL Constraint prohibits a database value from being NULL.

NOT NULL Constraint allows or disallows INSERTs or UPDATEs of rows containing a NULL in a specified column.

UNIQUE Constraint

UNIQUE Constraint prohibits multiple rows from having the same value in the same column or combination of columns, but allows some values to be NULL.

PRIMARY KEY Constraint

PRIMARY KEY Constraint combines a "NOT NULL Constraint" and a "UNIQUE Constraint".

That is, a PRIMARY KEY Constraint prohibits multiple rows from having the same value in the same column or combination of columns, and prohibits values from being NULL.

FOREIGN KEY Constraint

FOREIGN KEY Constraint requires values in one table to match values in the same table or in another table.

FOREIGN KEY Constraint designates a column of the table as the FOREIGN KEY, and establishes a Relationship between "the Foreign Key of the table" and "a Primary Key or a Unique Key of another table".

The Primary Key or the Unique Key of "the other table" in this Relationship is called the Referenced Key.

CHECK Constraint

CHECK Constraint requires a column value in the database to comply with a "Specified Condition".

REF Column Constraints

You can find detailed information on REF Columns in the "Oracle® Database, Object-Relational Developer's Guide".

Rules for REF columns and attributes can be enforced by the use of Constraints.

In Oracle Database, a REF column or attribute can be Unconstrained or Constrained using a SCOPE clause or a Referential Constraint clause.

When a REF column is Unconstrained, it may store object references to row objects contained in any object table of the corresponding object type.

Oracle Database DOES NOT ENSURE that the object references stored in such columns point to valid and existing row objects. Therefore, REF columns may contain object references that DO NOT point to any existing row object. Such REF values are referred to as Dangling References.

A REF column CAN BE CONSTRAINED with a REFERENTIAL Constraint similar to the specification for Foreign Keys. The rules for Referential Constraints apply to such columns. That is, the object reference stored in these columns MUST point to a valid and existing row object in the specified object table.

PRIMARY KEY Constraints CANNOT be specified for REF columns.

However, you CAN specify NOT NULL Constraints for REF columns.

For more information on REF Column Constraints, please refer to the "Oracle® Database, Object-Relational Developer's Guide".

A Section of the ER Model of the European Parliament

We will use a Section of Our ER Model of the European Parliament seen below, for Constraint Creation Examples.

This model contains only a few of the Entities from Our ER Model of the European Parliament, which we have already developed in Chapter 2—Data Modeling and Normalization.

A Section of the ER Model of the European Parliament for Constraint Examples
A Section of the ER Model of the European Parliament for Constraints

During the Database Design Process, using the ER Model, we mapped Entities into Tables:

Table Instance Chart

A Table Instance Chart is used during the Database Design Process for preparing the SQL Scripts that create the Database Objects.

A Table Instance Chart is part of the Database Design Process and it is one of the "Preparation Steps" BEFORE "the ER Model elements are turned into Database Objects".

Database Objects are derived from ER Models.

When working on a Table Instance Chart;

Below is the Table Instance Chart for the MEPS table.

Column Name Key Type Null / Unique FK Table FK Column Data Type Length
mep_id PK NN/U NUMBER 10
first_name VARCHAR2 120
last_name NN VARCHAR2 120
salary NUMBER (9,2)
bonus_pct NUMBER (5,4)
email NN/U VARCHAR2 240
tel VARCHAR2 20
internet VARCHAR2 120
start_date DATE
country_id FK COUNTRIES country_id VARCHAR2 4
pg_id FK POLITICAL_GROUPS pg_id NUMBER 10
pg_chair_or_cochair1 FK MEPS mep_id NUMBER 10
pg_cochair2 FK MEPS mep_id NUMBER 10

Table Instance Chart—PRIMARY KEY

A Primary Key (PK) is a "Column or a Set of Columns " that UNIQUELY IDENTIFY Each Row in a Database Table.

Each Table MUST have a Primary Key (PK).

The Primary Key (PK) MUST be UNIQUE.

The Primary Key (PK) MAY NOT be NULL.

The UID of an Entity in an ER Model, will map into a Primary Key (PK) in its corresponding Table in the Database.

A UID in ER Model becomes a Primary Key in Database..

In the Table Instance Chart for the MEPS table, we can see that the column mep_id is designated as the Primary Key (PK).

Each row in table MEPS can be UNIQUELY IDENTIFIED by the column mep_id.

Table Instance Chart—COMPOSITE PRIMARY KEY

A Primary Key consisting of Multiple Columns is called a Composite Primary Key or a Compound Primary Key.

In the Table Instance Chart for the MEPS table, we can see NO COLUMNS designated as a Composite Primary Key.

The single column mep_id is designated as the Primary Key (PK) for the MEPS table.

Table Instance Chart—ALTERNATE PRIMARY KEY

A table can have several Candidate Primary Keys.

A CANDIDATE Primary Key is a column or combination of columns that CAN Serve as the Primary Key for the table.

We select One of the Candidate Primary Keys to be the Primary Key for the table.

The Other Candidates MAY Become Alternate Primary Keys or Unique Keys.

We have already selected the "mep_id" column as the Primary Key for the MEPS table.

The column "email" is another Candidate Primary Key for the MEPS table.

NO TWO ROWS in the MEPS table can have identical emails.

The values of the "email" column MUST be NOT NULL and MUST be UNIQUE.

Therefore, the column "email" CAN BE an Alternate Primary Key for the MEPS table.

Below is the "email" column of the Table Instance Chart for the MEPS table.

Column Name Key Type Null / Unique FK Table FK Column Data Type Length
email NN/U VARCHAR2 240

The SQL Script which creates the MEPS table, will ensure that;

These are achieved by creating a NOT NULL Constraint (NN) and a UNIQUE Constraint (U) on the "email" column, within the SQL Script.

Table Instance Chart—FOREIGN KEY

Relationships in an ER Model are mapped into Foreign Keys in the Database.

A Relationship in ER Model becomes a Foreign Key in Database..

As we can see in the ER Model of the European Parliament, there are a few Relationships regarding the Entities MEP, POLITICAL GROUP and the COUNTRY.

A Section of the ER Model of the European Parliament for Constraint Examples
A Section of the ER Model of the European Parliament for Constraints

From the point of view of the MEPS table under consideration, these Relationships are;

These Relationships are mapped into Foreign Keys in the Database Design stage.

A Foreign Key (FK) is a "Column or a Combination of Columns" in One Table that REFERS to a Primary Key in the " Same Table or in Another Table".

Below is the Table Instance Chart for the MEPS table, showing the FOREIGN KEY columns only.

Column Name Key Type Null / Unique FK Table FK Column Data Type Length
country_id FK COUNTRIES country_id VARCHAR2 4
pg_id FK POLITICAL_GROUPS pg_id NUMBER 10
pg_chair_or_cochair1 FK MEPS mep_id NUMBER 10
pg_cochair2 FK MEPS mep_id NUMBER 10

SQL — CREATE TABLE Statement

Below is the SQL CREATE TABLE Statement which creates the MEPS table in our Database.

/* MEPS */
CREATE TABLE meps (
    mep_id                NUMBER(10)
        CONSTRAINT mep_id_pk PRIMARY KEY,
    first_name            VARCHAR2(120),
    last_name             VARCHAR2(120)
        CONSTRAINT last_name_nn NOT NULL,
    salary                NUMBER(9, 2),
    bonus_pct             NUMBER(5, 4),
    email                 VARCHAR2(240)
        CONSTRAINT email_nn NOT NULL
        CONSTRAINT email_unique UNIQUE,
    tel                   VARCHAR2(20),
    internet              VARCHAR2(120),
    start_date            DATE,
    country_id            VARCHAR2(4)
        CONSTRAINT country_id_fk
            REFERENCES countries ( country_id ),
    pg_id                 NUMBER(10)
        CONSTRAINT pg_id_fk
            REFERENCES political_groups ( pg_id ),
    pg_chair_or_cochair1  NUMBER(10)
        CONSTRAINT pg_chair_cochair1_fk
            REFERENCES meps ( mep_id ),
    pg_cochair2           NUMBER(10)
        CONSTRAINT pg_cochair2_fk
            REFERENCES meps ( mep_id )
);

To reach this SQL CREATE TABLE Statement, we have gone through many many steps:

Application Design Cycle

Our SQL CREATE TABLE Statement contains CONSTRAINT Clauses to create several Types of Constraints that we will now examine.

INLINE and OUT-OF-LINE Constraint Specifications

INLINE SPECIFICATION is, when you define an Integrity Constraint as part of an "Individual Column Definition" of an SQL CREATE TABLE Statement.

OUT-OF-LINE SPECIFICATION is, when an Integrity Constraint is declared as part of the "Table Definition" of an SQL CREATE TABLE Statement.

NOT NULL Constraints MUST be declared INLINE.

All Other Integrity Constraints CAN BE declared either INLINE or OUT-OF-LINE.

OUT-OF-LINE Constraint Definition can appear BEFORE or AFTER the Column Definitions.

SQL — NOT NULL CONSTRAINT

SQL — NOT NULL Constraint Clause

The lines seen below are part of our SQL CREATE TABLE Statement for the MEPS table.

last_name VARCHAR2(120)
    CONSTRAINT last_name_nn NOT NULL,

These lines define the column LAST_NAME (last_name VARCHAR2(120)).

At the same time, they define a NOT NULL Constraint on the column LAST_NAME (CONSTRAINT last_name_nn NOT NULL).

The name of this NOT NULL Constraint is LAST_NAME_NN.

This NOT NULL Constraint on the column LAST_NAME ensures that there will ALWAYS be a NONE NULL value in this column.

You MUST define a NOT NULL Constraint using INLINE SPECIFICATION, i.e. as part of the column definition.

If you specify neither NOT NULL, nor NULL, then the Default is NULL.

SQL — NOT NULL Constraint in Data Dictionary

You can query the newly created NOT NULL Constraints in the Data Dictionary.

The two SQL Statements below, query the NOT NULL Constraints in two different ways.

Query One
/******************************
Query the DD Table USER_CONSTRAINTS
on the CONSTRAINT_NAME 
***********************************/    
SELECT *
FROM USER_CONSTRAINTS
WHERE 1=1
AND CONSTRAINT_NAME='LAST_NAME_NN'

NOT NULL Constraint on LAST_NAME

Query Two
/******************************
Query the DD Tables USER_CONSTRAINTS
and USER_CONS_COLUMNS
for the table MEPS.
Query only the CONSTRAINT_TYPE='C'
which can either be a NOT NULL Constraint 
or a CHECK Constraint.  
******************************/     
SELECT UC.TABLE_NAME,
UC.CONSTRAINT_TYPE,
UC.CONSTRAINT_NAME,
UCC.COLUMN_NAME,
UC.SEARCH_CONDITION
FROM USER_CONSTRAINTS UC
JOIN USER_CONS_COLUMNS UCC
ON (UCC.CONSTRAINT_NAME=UC.CONSTRAINT_NAME)
WHERE 1=1
AND UC.TABLE_NAME='MEPS'
AND UC.CONSTRAINT_TYPE='C'

NOT NULL Constraints on TABLE MEPS

SQL — UNIQUE CONSTRAINT

SQL — UNIQUE Constraint on a Single Column

The lines seen below are part of our SQL CREATE TABLE Statement for the MEPS table.

email   VARCHAR2(240)
    CONSTRAINT email_nn NOT NULL
    CONSTRAINT email_unique UNIQUE,

These lines define the column EMAIL (email VARCHAR2(240)).

At the same time, they define;

on the column EMAIL.

In this section, we will investigate the UNIQUE Constraint on the column EMAIL — a single column.

The UNIQUE Constraint ensures that every value in a column is UNIQUE.

This means that no two rows of a table can have the same value in a specified column — NO DUPLICATE VALUES are allowed in the same column.

The UNIQUE Constraint ALLOWS the input of NULL Values in a column.

This is because;

However, in this case, two different types of constraints are defined on the EMAIL column:

email   VARCHAR2(240)
    CONSTRAINT email_nn NOT NULL
    CONSTRAINT email_unique UNIQUE,

These "two constraints together" ensure that;

Also, because of these two constraints, the column email becomes a Candidate Primary Key.

As we already have a Primary Key (the mep_id column), the column "email" is chosen as an Alternate Primary Key.

This UNIQUE Constraint on the single column "email" is specified INLINE, as part of the Column Definition.

SQL — UNIQUE Constraint in Data Dictionary (Single Column)

You can query this UNIQUE Constraint in the Data Dictionary.

Constraint Type 'U' is used for "UNIQUE Constraints".

/**********************
Query the DD Tables 
USER_CONSTRAINTS and 
USER_CONS_COLUMNS
to find out all the UNIQUE Constraints 
on table MEPS.
************************/
SELECT UC.TABLE_NAME,
UC.CONSTRAINT_TYPE,
UC.CONSTRAINT_NAME,
UCC.COLUMN_NAME,
UC.INDEX_NAME
FROM USER_CONSTRAINTS UC
JOIN USER_CONS_COLUMNS UCC
ON (UCC.CONSTRAINT_NAME=UC.CONSTRAINT_NAME)
WHERE 1=1
AND UC.TABLE_NAME='MEPS'
AND UC.CONSTRAINT_TYPE='U'

UNIQUE Constraint on a Single Column

The query result above, displays all the "UNIQUE Constraints" on "MEPS" table — "UC.CONSTRAINT_TYPE='U'".

We can see that there is only one UNIQUE Constraint defined on the "MEPS" table.

SQL — UNIQUE Constraint on Multiple Columns

We will use the SQL Create Table Statement of the MEP_PG_ROLES table, as an example on "UNIQUE Constraint on Multiple Columns".

Below is a section of Our ER Model of the European Parliament for this purpose.

A Section of Our ER Model with MEP_PG_ROLE
A Section of Our ER Model for MEP_PG_ROLE

Below is the SQL CREATE TABLE Statement which creates the MEP_PG_ROLES table in our Database.

create table MEP_PG_ROLES
(mep_id	number(10)
    constraint mep_pg_roles_mep_id_fk
    references MEPS(mep_id)
    constraint mep_pg_roles_mep_id_nn not null
,pg_role_id	number(10)
    constraint mep_pg_roles_role_id_fk
    references ROLES(role_id)
    constraint mep_pg_roles_role_id_nn not null
,constraint mep_pg_roles_un
unique (mep_id, pg_role_id)
); 

The lines below which are part of the SQL CREATE TABLE Statement, define a UNIQUE Constraint named MEP_PG_ROLES_UN on two columns of the table:

,constraint mep_pg_roles_un
unique (mep_id, pg_role_id)
; 

This UNIQUE Constraint named MEP_PG_ROLES_UN on the multiple columns "mep_id" and "pg_role_id" is specified OUT-OF-LINE, as part of the Table Definition.

A UNIQUE Constraint on "multiple columns" such as the one just created on "mep_id" and "pg_role_id" can also be called a Composite Unique Key Constraint.

A Composite Unique Key Constraint MUST BE Defined OUT-OF-LINE, as part of the Table Definition.

To Satisfy a Composite Unique Key Constraint:

SQL — UNIQUE Constraint in Data Dictionary (Multiple Columns)

Let's query this Composite Unique Key Constraint in the Data Dictionary.

/**********************
Query the DD Tables 
USER_CONSTRAINTS and 
USER_CONS_COLUMNS
to find out 
all the UNIQUE Constraints 
on table MEP_PG_ROLES.
*****
Because there are MULTIPLE COLUMNS,
we can ORDER BY the POSITION column of 
the USER_CONS_COLUMNS table.
************************/    
SELECT UC.TABLE_NAME,
UC.CONSTRAINT_TYPE,
UC.CONSTRAINT_NAME,
UCC.COLUMN_NAME,
UCC.POSITION,
UC.INDEX_NAME
FROM USER_CONSTRAINTS UC
JOIN USER_CONS_COLUMNS UCC
ON (UCC.CONSTRAINT_NAME=UC.CONSTRAINT_NAME)
WHERE 1=1
AND UC.TABLE_NAME='MEP_PG_ROLES'
AND UC.CONSTRAINT_TYPE='U'
ORDER BY UCC.POSITION

UNIQUE Constraint on Multiple Columns

Beauty in Most Unexpected Places
Beauty In Most Unexpected

SQL — PRIMARY KEY CONSTRAINT

SQL — PRIMARY KEY Constraint on a Single Column

The lines seen below are part of our SQL CREATE TABLE Statement for the MEPS table.

mep_id  NUMBER(10)
CONSTRAINT  mep_id_pk PRIMARY KEY,

These lines define the column MEP_ID (mep_id NUMBER(10)).

At the same time, they define a PRIMARY KEY Constraint on the column MEP_ID (CONSTRAINT mep_id_pk PRIMARY KEY).

The name of this PRIMARY KEY Constraint is MEP_ID_PK.

This PRIMARY KEY Constraint is specified INLINE as part of the column definition.

This PRIMARY KEY Constraint named MEP_ID_PK, enables each row to be uniquely identified by the values in the MEP_ID column.

The values of the MEP_ID column:

A PRIMARY KEY Constraint combines a NOT NULL Constraint and a UNIQUE Constraint in one Declaration.

Therefore, to SATISFY a PRIMARY KEY Constraint:

SQL — PRIMARY KEY Constraint in DD (Single Column)

We can query this PRIMARY KEY Constraint in the Data Dictionary.

For PRIMARY KEY Constraints, Constraint Type 'P' is used.

/**********************
Query the DD Tables 
USER_CONSTRAINTS and
USER_CONS_COLUMNS 
to find out the 
Primary Key Constraint of the 
MEPS table.
***********************/
SELECT UC.OWNER,
UC.TABLE_NAME,
UC.CONSTRAINT_TYPE,
UC.CONSTRAINT_NAME,
UCC.COLUMN_NAME
FROM USER_CONSTRAINTS UC
JOIN USER_CONS_COLUMNS UCC
ON (UCC.CONSTRAINT_NAME=UC.CONSTRAINT_NAME)
WHERE 1=1
AND UC.TABLE_NAME='MEPS'
AND UC.CONSTRAINT_TYPE='P'

Query the PRIMARY KEY in Data Dictionary

The result of the query is displayed above. There is always ONE Primary Key Constraint for a Table, made up of One or More Columns.

In this case, the PRIMARY KEY Constraint (CONSTRAINT_TYPE='P') is made up of a Single Column — MEP_ID.

SQL — PRIMARY KEY Constraint on Multiple Columns

Below is the SQL CREATE TABLE Statement for the table MEPS_HISTORY.

create table	MEPS_HISTORY
(mep_id	number(10)
 constraint meps_history_mep_id_nn not null
 constraint meps_history_mep_id_fk
    references MEPS(mep_id)
,start_date	date
 constraint meps_history_start_date_nn not null
,end_date date
 constraint meps_history_end_date_nn not null	
,role_id number(10)
 constraint meps_history_role_code_nn not null
 constraint meps_history_role_code_fk
    references ROLES(role_id)
,pg_id number(10)
 constraint meps_history_pg_id_fk 
    references POLITICAL_GROUPS(pg_id)
,constraint meps_history_pk 
 primary key(mep_id,start_date)
,constraint meps_history_dates_check
 check(start_date < end_date)
);

The lines below which are part of the SQL CREATE TABLE Statement, define a PRIMARY KEY Constraint named MEPS_HISTORY_PK on the two columns of the table MEPS_HISTORY:

,constraint meps_history_pk 
 primary key(mep_id,start_date)

This PRIMARY KEY Constraint named MEPS_HISTORY_PK on the multiple columns "mep_id" and "start_date" is specified OUT-OF-LINE, as part of the Table Definition.

A PRIMARY KEY Constraint on "multiple columns" such as the one just created on the "mep_id" and "start_date" columns, is also called a Composite Primary Key Constraint.

A Composite Primary Key Constraint MUST BE defined OUT-OF-LINE as part of the Table Definition.

SQL — PRIMARY KEY Constraint in DD (Multiple Columns)

We can query this Composite Primary Key Constraint in the Data Dictionary as follows.

/**********************
Query the DD Tables 
USER_CONSTRAINTS and
USER_CONS_COLUMNS 
to find out the 
Primary Key Constraint of the 
MEPS_HISTORY table.
Because this is a constraint with 
multiple columns, we can order the 
query results by the POSITION column of 
the USER_CONS_COLUMNS table.
***********************/
SELECT UC.OWNER,
UC.TABLE_NAME,
UC.CONSTRAINT_TYPE,
UC.CONSTRAINT_NAME,
UCC.COLUMN_NAME,
UCC.POSITION
FROM USER_CONSTRAINTS UC
JOIN USER_CONS_COLUMNS UCC
ON (UCC.CONSTRAINT_NAME=UC.CONSTRAINT_NAME)
WHERE 1=1
AND UC.TABLE_NAME='MEPS_HISTORY'
AND UC.CONSTRAINT_TYPE='P'
ORDER BY UCC.POSITION

Query the PRIMARY KEY in Data Dictionary

SQL — FOREIGN KEY CONSTRAINT

FOREIGN KEY Constraint — About

A Foreign Key Constraint, which is also called a Referential Integrity Constraint, designates a column as the Foreign Key, and establishes a Relationship between that Foreign Key and a specified Primary Key or Unique Key, called the Referenced Key.

A Composite Foreign Key designates a combination of columns as the Foreign Key.

The table containing the Foreign Key is called the CHILD Object.

The table containing the Referenced Key is called the PARENT Object.

The Foreign Key and the Referenced Key can be in the SAME Table.

In this case, the PARENT Table and the CHILD Table are the SAME Table.

If you identify only the PARENT Table and omit the Foreign Key Column name, then the Foreign Key automatically References the Primary Key of the PARENT Table.

The corresponding column or columns of the Foreign Key and the Referenced Key MUST match "in Order" and "in Data Type".

You CAN define a Foreign Key Constraint "ON a Single Column", either INLINE or OUT-OF-LINE.

You MUST specify a Composite Foreign Key Constraint OUT-OF-LINE.

FOREIGN KEY Constraint — REFERENCES Clause

Foreign Key Constraints use the REFERENCES Clause.

When you specify a Foreign Key Constraint INLINE, you ONLY need the REFERENCES Clause.

When you specify a Foreign Key Constraint OUT-OF-LINE, you MUST ALSO specify the FOREIGN KEY Keyword and one or more columns.

REFERENCES Clause — INLINE Specification

Below is an example of an INLINE Specification of a FOREIGN KEY Constraint (PG_ID_FK).

pg_id NUMBER(10)
    CONSTRAINT pg_id_fk
        REFERENCES political_groups(pg_id),

Only the REFERENCES Clause is used.

Only the REFERENCES Clause is SUFFICIENT enough to define a FOREIGN KEY Constraint in an INLINE Specification.

Full SQL Statement of this constraint (PG_ID_FK), can be seen below.

/* MEPS */
CREATE TABLE meps (
    mep_id NUMBER(10)
        CONSTRAINT mep_id_pk PRIMARY KEY,
    first_name VARCHAR2(120),
    last_name VARCHAR2(120)
        CONSTRAINT last_name_nn NOT NULL,
    salary NUMBER(9, 2),
    bonus_pct NUMBER(5, 4),
    email VARCHAR2(240)
        CONSTRAINT email_nn NOT NULL
        CONSTRAINT email_unique UNIQUE,
    tel VARCHAR2(20),
    internet VARCHAR2(120),
    start_date DATE,
    country_id VARCHAR2(4)
        CONSTRAINT country_id_fk
            REFERENCES countries ( country_id ),
    pg_id NUMBER(10)
        CONSTRAINT pg_id_fk
            REFERENCES political_groups ( pg_id ),
    pg_chair_or_cochair1  NUMBER(10)
        CONSTRAINT pg_chair_cochair1_fk
            REFERENCES meps ( mep_id ),
    pg_cochair2 NUMBER(10)
        CONSTRAINT pg_cochair2_fk
            REFERENCES meps ( mep_id )
);

SQL Statement above, shows a FOREIGN Key Constraint defined INLINE on the PG_ID column of the MEPS table.

The name of this FOREIGN Key Constraint is PG_ID_FK.

This constraint guarantees that every value in the PG_ID column of the MEPS table, WILL MATCH a value in the Primary Key of POLITICAL_GROUPS table (the PG_ID column).

Therefore, NO INCORRECT VALUES can exist in the PG_ID column of the MEPS table.

However, a FOREIGN Key value MAY BE NULL. This means that, PG_ID column of the MEPS table MAY HAVE a NULL value.

A FOREIGN Key value MUST MATCH an existing value in the PARENT Table, or be NULL.

REFERENCES Clause — OUT-OF-LINE Specification

Below is an example of an OUT-OF-LINE Specification of a FOREIGN KEY Constraint (PG_ID_FK).

,CONSTRAINT pg_id_fk FOREIGN KEY (pg_id)
    REFERENCES political_groups ( pg_id )

"REFERENCES Clause + FOREIGN KEY Keyword" are BOTH used.

NOT Only the "REFERENCES Clause", But ALSO the "FOREIGN KEY Keyword" MUST BE USED in an OUT-OF-LINE Specification.

Full SQL Statement of this constraint (PG_ID_FK), can be seen below.

/* MEPS */
CREATE TABLE meps (
    mep_id NUMBER(10)
        CONSTRAINT mep_id_pk PRIMARY KEY,
    first_name VARCHAR2(120),
    last_name VARCHAR2(120)
        CONSTRAINT last_name_nn NOT NULL,
    salary NUMBER(9, 2),
    bonus_pct NUMBER(5, 4),
    email VARCHAR2(240)
        CONSTRAINT email_nn NOT NULL
        CONSTRAINT email_unique UNIQUE,
    tel VARCHAR2(20),
    internet VARCHAR2(120),
    start_date DATE,
    country_id VARCHAR2(4)
        CONSTRAINT country_id_fk
            REFERENCES countries ( country_id ),
    pg_id NUMBER(10),
    pg_chair_or_cochair1  NUMBER(10)
        CONSTRAINT pg_chair_cochair1_fk
            REFERENCES meps ( mep_id ),
    pg_cochair2 NUMBER(10)
        CONSTRAINT pg_cochair2_fk
            REFERENCES meps ( mep_id )
    ,CONSTRAINT pg_id_fk FOREIGN KEY (pg_id)
        REFERENCES political_groups ( pg_id )
    );

SQL Statement above, shows a FOREIGN Key Constraint defined OUT-OF-LINE on the PG_ID column of the MEPS table.

The name of this FOREIGN Key Constraint is PG_ID_FK.

This constraint guarantees that every value in the PG_ID column of the MEPS table, WILL MATCH a value in the Primary Key of POLITICAL_GROUPS table (the PG_ID column).

Therefore, NO INCORRECT VALUES can exist in the PG_ID column of the MEPS table.

However, a FOREIGN Key value MAY BE NULL. This means that, PG_ID column of the MEPS table MAY HAVE NULL values.

A FOREIGN Key value MUST MATCH an existing value in the PARENT Table, or be NULL.

FOREIGN KEY Constraint — ON DELETE Clause

The ON DELETE Clause of a FOREIGN KEY Constraint definition lets you determine how Oracle Database automatically maintains Referential Integrity, IF you remove a Referenced Primary Key value or a Referenced Unique Key value.

ON DELETE Clause — Default Behaviour

If you OMIT the ON DELETE Clause, then Default Behaviour takes action.

If you OMIT the ON DELETE Clause, and Default Behaviour takes place, then Oracle DOES NOT ALLOW you to DELETE Referenced Key values in the PARENT Table that have Dependent Rows in the CHILD Table.

Let's assume that the FOREIGN Key Constraint (PG_ID_FK) is created using the SQL Statement below:

/* MEPS */
CREATE TABLE meps (
    mep_id NUMBER(10)
        CONSTRAINT mep_id_pk PRIMARY KEY,
    first_name VARCHAR2(120),
    last_name VARCHAR2(120)
        CONSTRAINT last_name_nn NOT NULL,
    salary NUMBER(9, 2),
    bonus_pct NUMBER(5, 4),
    email VARCHAR2(240)
        CONSTRAINT email_nn NOT NULL
        CONSTRAINT email_unique UNIQUE,
    tel VARCHAR2(20),
    internet VARCHAR2(120),
    start_date DATE,
    country_id VARCHAR2(4)
        CONSTRAINT country_id_fk
            REFERENCES countries ( country_id ),
    pg_id NUMBER(10)
        CONSTRAINT pg_id_fk
            REFERENCES political_groups ( pg_id ),
    pg_chair_or_cochair1  NUMBER(10)
        CONSTRAINT pg_chair_cochair1_fk
            REFERENCES meps ( mep_id ),
    pg_cochair2 NUMBER(10)
        CONSTRAINT pg_cochair2_fk
            REFERENCES meps ( mep_id )
    );
    

These are the lines where the constraint (PG_ID_FK) is created:

pg_id NUMBER(10)
    CONSTRAINT pg_id_fk
        REFERENCES political_groups(pg_id),

As we can see the ON DELETE Clause is OMITTED.

There is NO ON DELETE Clause.

Therefore, Default Behaviour will take action.

If we want to remove/delete a row from the PARENT Table which is the POLITICAL_GROUPS table, with a specific PG_ID value that has CHILD Rows in the CHILD Table which is the MEPS table, then Oracle WILL NOT ALLOW this happen.

The query below gives us the Political Groups, and the number of the Member of the Parliaments in each Political Group.

    SELECT PG_ID, COUNT(*) MEP_TOTAL
    FROM MEPS
    GROUP BY PG_ID
    ORDER BY MEP_TOTAL DESC

Here is the output in SQL Developer.

Number of MEPS in Political Groups

If now we try to delete the row with the PG_ID value of 20 in the PARENT Table, which is the POLITICAL_GROUPS, Oracle will throw an ERROR.

This is because, there are 288 CHILD Rows in the MEPS table with a PG_ID value of 20.

We can see the SQL Statement and the resulting error below.

DELETE FROM POLITICAL_GROUPS 
WHERE PG_ID=20       

Error starting at line : 1 in command -
DELETE FROM POLITICAL_GROUPS 
WHERE PG_ID=20
Error report -
ORA-02292: integrity constraint (KAYE.PG_ID_FK) violated - child record found                

CANNOT DELETE from Political Groups because of the Foreign Key Constraint.

This is the ON DELETE Clause Default Behaviour in action when the ON DELETE Clause is OMITTED.

European Parliament in Brussels
European Parliament in Brussels

ON DELETE Clause — CASCADE

Specify CASCADE if you want Oracle to remove DEPENDENT FOREIGN Key Rows automatically/implicitly.

ON DELETE CASCADE causes the DEPENDENT Rows in the CHILD Table to be deleted automatically/implicitly by Oracle, when a row in the PARENT Table is deleted.

In our example, the FOREIGN KEY Constraint is "PG_ID_FK":

SELECT * 
FROM POLITICAL_GROUPS
ORDER BY PG_ID    

The query above retrieves all the rows in the PARENT Table which is POLITICAL_GROUPS.

POLITICAL_GROUPS in SQL Developer
POLITICAL_GROUPS in SQL Developer

Let's focus on the row with PG_ID=20.

This is the political group named 'Group of the European People's Party(Christian Democrats) and European Democrats' with the PG_CODE='EPP-ED'.

POLITICAL_GROUPS in SQL Developer

We already know from a previous query that there are 288 Members of the Parliament belonging to this Political Group.

This information is held in the CHILD Table or the DEPENDENT TableMEPS.

Below is a query to retrive all the Members of the Parliament belonging to the Political Group 'EPP-ED' (PG_ID=20). Only some of the columns are selected.

SELECT M.MEP_ID,
M.PG_ID,
M.FIRST_NAME,
M.LAST_NAME,
M.COUNTRY_ID,
M.INTERNET
FROM MEPS M
WHERE 1=1
AND M.PG_ID=20
ORDER BY M.MEP_ID

and here is the result in SQL Developer:

MEPS of PG_ID=20 in SQL Developer

If we specify the ON DELETE CASCADE Clause when defining the FOREIGN KEY "PG_ID_FK", and at some stage, we DELETE the row with PG_ID=20 from the PARENT Table POLITICAL_GROUPS, then all of the 288 DEPENDENT rows in the CHILD Table MEPS, with PG_ID=20 will be automatically/implicitly DELETED by Oracle.

Below is the Constraint Definition with the ON DELETE CASCADE Clause within the CHILD Table MEPS:

pg_id NUMBER(10)
    CONSTRAINT pg_id_fk
        REFERENCES political_groups(pg_id)
        ON DELETE CASCADE,

This is how ON DELETE CASCADE works.

ON DELETE Clause — SET NULL

ON DELETE SET NULL works similar to ON DELETE CASCADE.

Only, instead of removing the DEPENDENT FOREIGN Key Rows automatically/implicitly, Oracle converts the DEPENDENT FOREIGN Key Values to NULL automatically/implicitly, when a row in the PARENT Table is deleted.

Let's take the same example in the ON DELETE CASCADE section.

If we specify the ON DELETE SET NULL Clause when defining the FOREIGN KEY "PG_ID_FK", and at some stage, we DELETE the row with PG_ID=20 from the PARENT Table POLITICAL_GROUPS, then Oracle will automatically/implicitly convert the PG_ID values of all the 288 DEPENDENT rows in the CHILD Table MEPS, from 20 to NULL.

Set the values PG_ID=20 to NULLS in the MEPS table.

Below is the Constraint Definition with the ON DELETE SET NULL Clause within the CHILD Table MEPS:

pg_id NUMBER(10)
    CONSTRAINT pg_id_fk
    REFERENCES political_groups(pg_id)
    ON DELETE SET NULL,

This is how ON DELETE SET NULL works.

FOREIGN KEY Constraint — Data Dictionary Query 1

We can query a FOREIGN KEY Constraint in the Data Dictionary.

For FOREIGN KEY Constraints, Constraint Type 'R' is used.

'R' stands for Referential Integrity.

Table MEPS is created using the SQL Statement below.

/* MEPS */
CREATE TABLE meps (
mep_id NUMBER(10)
    CONSTRAINT mep_id_pk PRIMARY KEY,
first_name VARCHAR2(120),
last_name VARCHAR2(120)
    CONSTRAINT last_name_nn NOT NULL,
salary NUMBER(9, 2),
bonus_pct NUMBER(5, 4),
email VARCHAR2(240)
    CONSTRAINT email_nn NOT NULL
    CONSTRAINT email_unique UNIQUE,
tel VARCHAR2(20),
internet VARCHAR2(120),
start_date DATE,
country_id VARCHAR2(4)
    CONSTRAINT country_id_fk
        REFERENCES countries ( country_id ),
pg_id NUMBER(10)
    CONSTRAINT pg_id_fk
        REFERENCES political_groups ( pg_id ),
pg_chair_or_cochair1 NUMBER(10)
    CONSTRAINT pg_chair_cochair1_fk
        REFERENCES meps ( mep_id ),
pg_cochair2 NUMBER(10)
    CONSTRAINT pg_cochair2_fk
        REFERENCES meps ( mep_id )
);

We will now query the DD—Data Dictionary for all the FOREIGN Key Constraints of the MEPS table.

/************************************
Query the DD Tables 
USER_CONSTRAINTS and 
USER_CONS_COLUMNS to retrieve 
the Foreign Key Constraints of the 
MEPS table.
**************************************/
SELECT UC.OWNER,
UC.TABLE_NAME,
UC.CONSTRAINT_TYPE,
UC.CONSTRAINT_NAME,
UCC.COLUMN_NAME
FROM USER_CONSTRAINTS UC
JOIN USER_CONS_COLUMNS UCC
ON (UCC.CONSTRAINT_NAME=UC.CONSTRAINT_NAME)
WHERE 1=1
AND UC.TABLE_NAME='MEPS'
AND UC.CONSTRAINT_TYPE='R'
ORDER BY UC.CONSTRAINT_NAME

Query the FOREIGN KEY in Data Dictionary

The SQL query above retrieves all the FOREIGN KEY / REFERENTIAL INTEGRITY Constraints of the MEPS table.

However, it only displays; the "Names of the Constraints "and the "Foreign Key Columns".

It DOES NOT give any information on the PARENT Table, and the REFERENCED KEY of the PARENT Table.

We need another SQL query to find this information, which is in the next section.

FOREIGN KEY Constraint — Data Dictionary Query 2

The query below retrieves almost everything we would like to know about a Foreign Key;

/************************************
Query the DD Tables 
USER_CONSTRAINTS and 
USER_CONS_COLUMNS to retrieve 
the Foreign Key Constraints 
as well as the Parent Table information 
for the Foreign Keys of the MEPS table.
**************************************/
SELECT child_table.table_name "Child Table",
child_table.constraint_type "Child Constraint Type",
child_table.constraint_name "Child Constraint Name",
child_column.column_name "Foreign Key",
parent_table.table_name "Parent Table",
parent_table.constraint_type "Parent Constraint Type",
child_table.r_constraint_name "Parent Constraint Name",
parent_column.column_name "Referenced Key"
FROM user_constraints child_table
JOIN user_constraints parent_table 
ON ( parent_table.constraint_name = child_table.r_constraint_name )
JOIN user_cons_columns child_column 
ON ( child_column.constraint_name = child_table.constraint_name )
JOIN user_cons_columns parent_column 
ON ( parent_column.constraint_name = parent_table.constraint_name )
WHERE 1 = 1
AND child_table.table_name = 'MEPS'
AND child_table.constraint_type = 'R'

This query uses the two Data Dictionary tables;

Query the FOREIGN KEY in Data Dictionary

Here is the result in SQL Developer.

Query the FOREIGN KEY in Data Dictionary

This sums up querying Foreign Keys in the Data Dictionary.

SQL — CHECK CONSTRAINT

CHECK Constraint — About

A CHECK Constraint specifies a CONDITION that each row in the table MUST Satisfy.

To Satisfy the CHECK Constraint, each row in the table MUST make the CONDITION;

When Oracle evaluates a CHECK Constraint CONDITION for a particular row, any "Column Names" in the CONDITION "REFER to the Column Values in that row."

The syntax for INLINE and OUT-OF-LINE specification of CHECK Constraints are the same.

However, INLINE specification can REFER only to the "Column currently being defined", whereas OUT-OF-LINE specification can REFER to "Multiple Columns".

SQL —CHECK Constraint Example 1

Below is the SQL Statement which creates the table POLITICAL_GROUPS.

create table POLITICAL_GROUPS
(pg_id number(10)
    constraint pg_id_pk primary key
,pg_code varchar2(30)
    constraint pg_code_nn not null
    constraint pg_code_unique unique
,pg_name varchar2(120)
,address varchar2(240)
,postal_code varchar2(15)
,city varchar2(60)
    constraint pg_city_nn not null
,tel varchar2(20)
,email varchar2(240)
,internet varchar2(120)
,about clob
,institute_id number(10)
    constraint pg_institute_id_fk 
    references EU_INSTITUTES(institute_id)
);
    

As we can see, there is a NOT NULL and a UNIQUE constraint on the column PG_CODE:

,pg_code varchar2(30)
    constraint pg_code_nn not null
    constraint pg_code_unique unique    

Let's assume that we want to restrict the values input to the column PG_CODE, with the following values:

In this case, we can define a CHECK Constraint on the column PG_CODE as follows:

,pg_code varchar2(30)
    constraint check_pg_code CHECK
    (pg_code IN ('EPP-ED', 
    'PES',
    'Greens/EFA',
    'GUE/NGL',
    'IND/DEM',
    'ALDE',
    'UEN',
    'NI') )    

However, this CHECK Constraint allows NULL values in the column PG_CODE.

This is because, if the input value is NULL, then the expression

(pg_code IN ('EPP-ED', 
'PES',
'Greens/EFA',
'GUE/NGL',
'IND/DEM',
'ALDE',
'UEN',
'NI'))    

evaluates to NULL.

SQL —CHECK Constraint Example 2

Here is another CHECK Constraint example.

This CHECK Constraint example is on the table MEPS_HISTORY.

Below is the SQL CREATE TABLE Statement for the table MEPS_HISTORY.

create table MEPS_HISTORY
(mep_id	number(10)
    constraint meps_history_mep_id_nn not null
    constraint meps_history_mep_id_fk
        references MEPS(mep_id)
,start_date	date
    constraint meps_history_start_date_nn not null
,end_date date
    constraint meps_history_end_date_nn not null	
,role_id number(10)
    constraint meps_history_role_code_nn not null
    constraint meps_history_role_code_fk
        references ROLES(role_id)
,pg_id number(10)
    constraint meps_history_pg_id_fk 
        references POLITICAL_GROUPS(pg_id)
,constraint meps_history_pk 
    primary key(mep_id,start_date)
,constraint meps_history_dates_check
    check(start_date < end_date)
);

The lines below

,constraint meps_history_dates_check
check(start_date < end_date)

which are part of the SQL CREATE TABLE Statement, define a CHECK Constraint named MEPS_HISTORY_DATES_CHECK on the two columns of the table MEPS_HISTORY:

The CHECK Constraint named MEPS_HISTORY_DATES_CHECK ensures that the value in the "start_date" column is always LESS THAN (<) the value in the "end_date" column, within a row.

This CHECK Constraint named MEPS_HISTORY_DATES_CHECK on the multiple columns "start_date" and "end_date" is specified OUT-OF-LINE, as part of the Table Definition.

SQL —CHECK Constraint in Data Dictionary

The SQL Statement below, queries the constraints of the MEPS_HISTORY table with CONSTRAINT_TYPE='C'.

The query is on the Data Dictionary tables, USER_CONSTRAINTS and USER_CONS_COLUMNS.

SELECT UC.OWNER,
UC.TABLE_NAME,
UC.CONSTRAINT_TYPE,
UC.CONSTRAINT_NAME,
UCC.COLUMN_NAME,
UC.SEARCH_CONDITION
FROM USER_CONSTRAINTS UC
JOIN USER_CONS_COLUMNS UCC
ON (UCC.CONSTRAINT_NAME=UC.CONSTRAINT_NAME)
WHERE 1=1
AND UC.TABLE_NAME='MEPS_HISTORY'
AND UC.CONSTRAINT_TYPE='C'
ORDER BY UC.CONSTRAINT_NAME, UCC.COLUMN_NAME

Here is the result of the query in SQL Developer.

Query the CHECK Constraint in Data Dictionary

CONSTRAINT_TYPE column of the USER_CONSTRAINTS table, tells us the "type" of the constraint.

CONSTRAINT_TYPE='C' tells us that the Constraint is:

The SEARCH_CONDITION column of the USER_CONSTRAINTS table makes it clear whether the Constraint is a "NOT NULL Constraint" or not.

If it says "COLUMN_NAME" IS NOT NULL in the SEARCH_CONDITION column, then this is a "NOT NULL Constraint", else a "CHECK Constraint".

NOT NULL Constraints in Data Dictionary

Constraints marked with a rectangle are "NOT NULL Constraints".

Here are the result rows of the query displaying the CHECK Constraint "MEPS_HISTORY_DATES_CHECK".

Query the CHECK Constraint in Data Dictionary

The SEARCH_CONDITION column is the same as the CHECK Condition we defined in the SQL CREATE TABLE Statement of the MEPS_HISTORY:

,constraint meps_history_dates_check
check(start_date < end_date)

... and now, a breath of fresh air.

Breath of Fresh Air

CHECK Constraint — Design Considerations

A table can have multiple CHECK Constraints.

Multiple CHECK Constraints each with a Simple Condition enforcing a Single Business Rule,

are PREFERABLE to

a Single CHECK Constraint with a Complicated Condition enforcing Multiple Business Rules.

When a constraint is violated, Oracle returns an error identifying the constraint.

Such an error more precisely identifies the violated business rule, if the identified constraint enables a single business rule.

CHECK Constraints are used when Integrity Rules need to be enforced based on Logical Expressions — such as Comparisons.

It is NOT ADVISABLE to use CHECK Constraints, when any of the Other Types of Integrity Constraints CAN PROVIDE the necessary checking.

For More on Integrity Constraints

You can refer to the Oracle Documentation if you need more detailed information on Integrity Constraints.

You can find a list of these documents in the References.

Please keep in mind that the names of the documents may change in time.

References

just me